#include <iostream>
#include <atomic>
#include <utility>

template <typename T>
class shared_ptr {
private:
    T* ptr;
    std::atomic<std::size_t>* ref_count;

    void release() {
        if (ref_count && ref_count->fetch_sub(1, std::memory_order_acq_rel) == 1) {
            delete ptr;
            delete ref_count;
        }
    }

public:
    // 默认构造函数
    shared_ptr() : ptr(nullptr), ref_count(nullptr) {}

    // 构造函数
    explicit shared_ptr(T* p) : ptr(p), ref_count(p ? new std::atomic<std::size_t>(1) : nullptr) {}

    // 拷贝构造函数
    shared_ptr(const shared_ptr& other) : ptr(other.ptr), ref_count(other.ref_count) {
        if (ref_count) {
            ref_count->fetch_add(1, std::memory_order_relaxed);
        }
    }

    // 移动构造函数
    shared_ptr(shared_ptr&& other) noexcept : ptr(other.ptr), ref_count(other.ref_count) {
        other.ptr = nullptr;
        other.ref_count = nullptr;
    }

    // 析构函数
    ~shared_ptr() {
        release();
    }

    // 拷贝赋值操作符
    shared_ptr& operator=(const shared_ptr& other) {
        shared_ptr temp(other); // 使用拷贝构造函数创建临时对象
        swap(*this, temp);      // 交换当前对象和临时对象
        return *this;
    }

    // 移动赋值操作符
    shared_ptr& operator=(shared_ptr&& other) noexcept {
        if (this != &other) {
            release();
            ptr = other.ptr;
            ref_count = other.ref_count;
            other.ptr = nullptr;
            other.ref_count = nullptr;
        }
        return *this;
    }

    // 获取原始指针
    T* get() const { return ptr; }

    // 获取引用计数
    std::size_t use_count() const { return ref_count ? ref_count->load(std::memory_order_relaxed) : 0; }

    // 交换两个 shared_ptr 对象
    friend void swap(shared_ptr& first, shared_ptr& second) noexcept {
        using std::swap;
        swap(first.ptr, second.ptr);
        swap(first.ref_count, second.ref_count);
    }

    // 解引用操作符
    T& operator*() const { return *ptr; }

    // 成员访问操作符
    T* operator->() const { return ptr; }
};

// 测试结构体
struct Test {
    int value;
    Test(int v) : value(v) {}
    ~Test() {
        std::cout << "Destructor called for Test with value: " << value << std::endl;
    }
};

int main() {
    {
        // 创建第一个 shared_ptr 实例
        shared_ptr<Test> sp1(new Test(10));
        std::cout << "sp1 use count: " << sp1.use_count() << std::endl;

        {
            // 通过拷贝构造函数创建第二个 shared_ptr 实例
            shared_ptr<Test> sp2 = sp1;
            std::cout << "After copy construction:" << std::endl;
            std::cout << "sp1 use count: " << sp1.use_count() << std::endl;
            std::cout << "sp2 use count: " << sp2.use_count() << std::endl;
        }

        // 第二个 shared_ptr 实例离开作用域后
        std::cout << "After sp2 goes out of scope:" << std::endl;
        std::cout << "sp1 use count: " << sp1.use_count() << std::endl;

        // 移动构造函数测试
        shared_ptr<Test> sp3 = std::move(sp1);
        std::cout << "After move construction:" << std::endl;
        std::cout << "sp1 use count: " << sp1.use_count() << std::endl;
        std::cout << "sp3 use count: " << sp3.use_count() << std::endl;

        // 移动赋值操作符测试
        shared_ptr<Test> sp4(new Test(20));
        sp4 = std::move(sp3);
        std::cout << "After move assignment:" << std::endl;
        std::cout << "sp3 use count: " << sp3.use_count() << std::endl;
        std::cout << "sp4 use count: " << sp4.use_count() << std::endl;
    }

    // 所有 shared_ptr 实例都被销毁
    std::cout << "All shared_ptr instances have been destroyed." << std::endl;

    return 0;
}